package com.zenika.zenbinding.client.model;

import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.Widget;
import com.zenika.zenbinding.client.exception.DataMessage;
import com.zenika.zenbinding.client.feedback.FeedbackManager;
import com.zenika.zenbinding.client.handler.Handler;
import com.zenika.zenbinding.client.renderer.Renderer;

/**
 * A ListModel manages the access to a property of a BusinessObject, the validation and redirect errors of Validation or Conversion to a FeedbackManager. It is used in the case of the property has to
 * be synchronized with a selection of objects in a list. The property could be an Array, a List or an Object.
 * 
 * @author Zenika
 */
public class TableModel implements Model, CellModelListener {
  
  private BusinessObject[] sources;
  private Label[] headers;
  private Renderer[] renderers;
  private FeedbackManager manager;
  private DataMessage currentError;
  private String feedbackId;
  private Handler handler;
  
  public TableModel(BusinessObject[] sources, Label[] headers, Renderer[] renderers) {
    this.sources = sources;
    this.headers = headers;
    this.renderers = renderers;
  }
  
  public CellModel getCellModel(int row, int column) {
    CellModel cellModel = new CellModel(row, column, this.sources[row], this.renderers[column]);
    cellModel.addCellModelListener(this);
    return cellModel;
  }
  
  public boolean hasHeaders() {
    return (this.headers != null) ? true : false;
  }
  
  public Label getHeader(int column) {
    return this.headers[column];
  }
  
  public int getRowCount() {
    return this.sources.length;
  }
  
  public int getColumnCount() {
    return this.renderers.length;
  }
  
  /**
   * Notify the entering in error state to the feedback manager.
   * 
   * @param message
   * @param handler
   */
  public void fireError(DataMessage message, Handler handler) {
    if ( this.manager != null ) {
      if ( this.feedbackId != null ) {
        message.setMessage(message.getMessage() + " : " + this.feedbackId);
      }
      this.manager.enterErrorState(message, handler);
    }
  }
  
  /**
   * Notify the leaving of error state to the feedback manager;
   * 
   * @param handler
   */
  public void fireErrorStop(Handler handler) {
    if ( this.manager != null ) {
      this.manager.leaveErrorState(handler);
    }
  }
  
  public void onEnteringErrorState(int row, int column, Handler handler, DataMessage message) {
    // coordinates not used for the moment
    // FIXME debug this
    this.currentError = message;
    this.fireError(message, handler);
  }
  
  public void onLeavingErrorState(int row, int column, Handler handler) {
    // coordinates not used for the moment
    // FIXME debug this
    this.currentError = null;
    this.fireErrorStop(handler);
  }
  
  public void setFeedbackManager(FeedbackManager manager) {
    this.manager = manager;
  }
  
  public void setFeedbackManager(FeedbackManager manager, String feedbackId) {
    this.setFeedbackManager(manager);
    this.feedbackId = feedbackId;
  }
  
  public void setHandler(Handler handler) {
    this.handler = handler;
  }
  
  public Handler getHandler() {
    return this.handler;
  }
  
  public Widget getWidget() {
    return this.handler.getWidget();
  }
  
  public DataMessage getCurrentValidationState() {
    return this.currentError;
  }
  
  public DataMessage validate() {
    // FIXME implement this if possible?
    return this.currentError;
  }
  
}
